package com.etv.launcher.repository;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.BatteryManager;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import com.etv.launcher.common.enums.PmApplicationTypeEnum;
import com.etv.launcher.common.utils.ColorUtil;
import com.etv.launcher.common.utils.FileUtil;
import com.etv.launcher.common.utils.ObjectUtil;
import com.etv.launcher.common.utils.ToastUtil;
import com.etv.launcher.dao.ApplicationInfoDao;
import com.etv.launcher.model.entity.ApplicationInfoEntity;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.inject.Inject;

import dagger.hilt.android.qualifiers.ApplicationContext;
import lombok.Getter;

public class ApplicationInfoRepository {
    private Context context;

    private ApplicationInfoDao dao;

    private PackageManager pm;

    @Getter
    private MutableLiveData<Float> batteryLiveData;

    @Inject
    public ApplicationInfoRepository(@ApplicationContext Context context, ApplicationInfoDao dao) {
        this.context = context.getApplicationContext();
        this.dao = dao;
        this.pm = this.context.getPackageManager();

        //电量
        BatteryManager batteryManager = (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE);
        int batteryPct = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
        this.batteryLiveData = new MutableLiveData<>((float)batteryPct);
    }

    public LiveData<List<ApplicationInfoEntity>> getAppListLiveData() {
        return dao.queryApplicationListLive();
    }

    /**
     * 获取实际应用列表
     *
     * @param typeEnum 应用类型
     *                 0 系统应用，1用户安装应用，2所有应用
     * @return
     */
    private List<ApplicationInfo> getSystemInstalledApps(PmApplicationTypeEnum typeEnum) {
        PackageManager pm = context.getPackageManager();
        List<ApplicationInfo> apps;
        switch (typeEnum.getCode()) {
            case 0: // 系统应用
                apps = pm.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY);
                break;
            case 1: // 用户应用
                List<ApplicationInfo> allApps = pm.getInstalledApplications(PackageManager.GET_META_DATA);
                apps = new ArrayList<>();
                for (ApplicationInfo app : allApps) {
                    if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                        apps.add(app);
                    }
                }
                break;
            case 2: // 所有应用
                apps = pm.getInstalledApplications(PackageManager.GET_META_DATA);
                break;
            default:
                throw new IllegalArgumentException("Invalid appType: " + typeEnum);
        }

        return apps;
    }

    /**
     * 初始化应用
     */
    public void loadApplicationInfo() {
        //数据库存储数据
        List<String> dataPackageList = dao.queryAllPackageName();
        //所有实际应用的id
        List<String> allRealIdList = new ArrayList<>();

        //添加系统应用与用户应用
        allRealIdList.addAll(this.loadPmTypeApps(dataPackageList, PmApplicationTypeEnum.SYSTEM_APP));
        allRealIdList.addAll(this.loadPmTypeApps(dataPackageList, PmApplicationTypeEnum.USER_APP));

        //删除数据库中已经被卸载的数据
        dataPackageList.removeAll(allRealIdList);
        dao.deleteByPackageNames(dataPackageList);
    }

    private List<String> loadPmTypeApps(List<String> dataPackageList, PmApplicationTypeEnum pmType) {
        List<ApplicationInfo> appList = this.getSystemInstalledApps(pmType);

        //获取到新安装的列表
        List<ApplicationInfoEntity> installList = new ArrayList<>();
        List<String> allAppIdList = new ArrayList<>();

        ExecutorService executor = Executors.newFixedThreadPool(Math.max(2, Runtime.getRuntime().availableProcessors() * 2)); // **动态线程池**
        CountDownLatch latch = new CountDownLatch(appList.size());
        for (ApplicationInfo appInfo : appList) {
            allAppIdList.add(appInfo.packageName);

            if (dataPackageList.contains(appInfo.packageName)) {
                latch.countDown();
                continue;
            }

            executor.execute(() -> { // **全部耗时操作放入线程池**
                // 同步收集结果
                installList.add(createAppInfo(appInfo, pmType));
                latch.countDown();
            });
        }

        try {
            latch.await();
            dao.insert(installList.toArray(new ApplicationInfoEntity[0]));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            executor.shutdownNow();
        }

        return allAppIdList;
    }

    private ApplicationInfoEntity createAppInfo(ApplicationInfo appInfo, PmApplicationTypeEnum pmType) {
        String tvApplicationId = context.getPackageName();
        ApplicationInfoEntity dto = new ApplicationInfoEntity();
        String packageName = appInfo.packageName;

        // 并行处理Drawable转换（耗时操作）
        Drawable icon = pm.getApplicationIcon(appInfo);
        Bitmap iconBitmap = FileUtil.drawableToBitmap(icon);
        String iconPath = new File(context.getExternalCacheDir(), "icon/" + appInfo.packageName + ".png").getPath();
        FileUtil.saveBitmap(iconBitmap, iconPath);

        // 并行处理Banner
        Drawable banner = pm.getApplicationBanner(appInfo);
        if (banner != null) {
            Bitmap bannerBitmap = FileUtil.drawableToBitmap(banner);
            String bannerPath = new File(context.getExternalCacheDir(), "banner/" + appInfo.packageName + ".png").getPath();
            dto.setBannerPath(bannerPath);
            FileUtil.saveBitmap(bannerBitmap, bannerPath);
        }

        // 主线程独有操作移到外部
        dto.setIconPath(iconPath);
        dto.setApplicationId(packageName);
        dto.setApplicationId(appInfo.packageName);
        dto.setAppName(pm.getApplicationLabel(appInfo).toString());
        dto.setPrimaryColor(ColorUtil.getPrimaryColor(pm.getApplicationIcon(appInfo)));
        dto.setBackColor(ColorUtil.generateBackgroundFromColor(dto.getPrimaryColor()));
        dto.setPmType(pmType == PmApplicationTypeEnum.SYSTEM_APP ? 0 : 1);
        dto.setIconType(0);
        dto.setVisible(pmType == PmApplicationTypeEnum.USER_APP && !dto.getApplicationId().equals(tvApplicationId));

        return dto;
    }

    /**
     * 添加新应用
     *
     * @param applicationId
     */
    public void addApplication(String applicationId) {
        Executors.newSingleThreadExecutor().execute(() -> {
            try {
                ApplicationInfo appInfo = pm.getApplicationInfo(applicationId, 0);
                if (ObjectUtil.isNotBlank(appInfo)) {
                    PmApplicationTypeEnum pmType = (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ? PmApplicationTypeEnum.USER_APP : PmApplicationTypeEnum.SYSTEM_APP;
                    dao.insert(createAppInfo(appInfo, pmType));
                }
            } catch (Exception e) {
                ToastUtil.show(context, "加载新应用失败！");
            }
        });
    }

    public void removeApplication(String applicationId) {
        Executors.newSingleThreadExecutor().execute(() -> {
            dao.deleteByPackageNames(Arrays.asList(applicationId));
        });


    }

    public void setBatteryLevel(float batteryLevel){
        Executors.newSingleThreadExecutor().execute(()->{
            batteryLiveData.postValue(batteryLevel);
        });
    }
}
